/**
 * @file: volcano_api.js
 * @brief: 火山引擎API库JavaScript实现（基于Lua RPC）
 * @date: 2025-10-16
 */

/**
 * 火山引擎API客户端RPC接口封装类
 * 用于提供远程调用Lua火山引擎API的JavaScript接口
 */
class VolcanoApiRpc {
    /**
     * 构造函数
     * @param {LuaRpc} luaRpc - Lua RPC实例
     */
    constructor(luaRpc) {
        this.luaRpc = luaRpc;
        this._initialized = false;
        // 创建初始化Promise但不等待其完成
        // 使用Promise的catch来避免未处理的Promise拒绝
        this._initializationPromise = this._initialize().catch(error => {
            console.error('VolcanoApiRpc initialization failed:', error);
        });
    }

    /**
     * 异步初始化方法
     * 用于在类初始化时加载volcano_api模块
     * @private
     */
    async _initialize() {
        try {
            // 注册volcano_api库
            console.log('VolcanoApiRpc: Registering volcano_api module...');
            await this.luaRpc.runCode(`
                if not cjson then
                    cjson = require("cjson")
                    print('cjson module registered')
                else
                    print('cjson module already registered')
                end
                if not volcano_api then
                    volcano_api = require("volcano_api")
                    print('volcano_api module registered')
                else
                    print('volcano_api module already registered')
                end
            `);
            
            console.log('VolcanoApiRpc: Module loading script executed');
            this._initialized = true;
        } catch (error) {
            console.error('Failed to initialize VolcanoApiRpc and load required modules:', error);
            this._initialized = false;
            throw error;
        }
    }

    /**
     * 确保VolcanoApiRpc已初始化
     * 用于在调用火山引擎API方法前检查初始化状态
     * @private
     */
    async _ensureInitialized() {
        if (!this._initialized) {
            // 如果尚未初始化完成，则等待初始化
            if (!this._initializationPromise) {
                this._initializationPromise = this._initialize();
            }
            await this._initializationPromise;
        }
    }

    /**
     * 创建火山引擎API实例
     * @param {Object} config - 配置参数
     * @param {string} config.modelId - 模型ID
     * @param {string} config.apiKey - API密钥
     * @param {string} config.thinking - 思考模式(disabled/enabled/auto)
     * @param {number} config.maxTokens - 最大生成令牌数
     * @param {number} config.temperature - 采样温度
     * @param {number} config.maxContextLength - 最大上下文消息数
     * @returns {Promise<VolcanoApi>} - 返回火山引擎API对象
     */
    async create(config) {
        console.log(`VolcanoApiRpc.create() 被调用，配置:`, config);
        try {
            // 确保VolcanoApiRpc已初始化
            await this._ensureInitialized();
            
            // 参数检查
            if (!config || typeof config !== 'object') {
                throw new Error('Invalid configuration object');
            }
            
            if (!config.modelId || !config.apiKey) {
                throw new Error('modelId and apiKey are required');
            }
            
            // 生成一个唯一的标识符用于在Lua中引用这个API对象
            const apiId = 'volcanoApi_' + Date.now() + '_' + Math.random().toString(36).slice(2, 11);
            
            // 转换配置对象为Lua代码
            const configString = JSON.stringify(config)
                .replace(/\\"/g, '\\\\"')
                .replace(/"/g, '\\"');
            
            // 执行volcano_api.create函数，确保cjson模块已加载
            const luaCode = `
                -- 确保cjson模块已加载
                local config = cjson.decode("${configString}")
                ${apiId}, err = volcano_api.create(config)
            `;
            console.log(`执行Lua代码:`, luaCode);
            await this.luaRpc.runCode(luaCode);
            
            // 获取创建结果
            const errorResult = await this.luaRpc.getGlobal('err');
            const apiResult = await this.luaRpc.getGlobal(apiId);
            
            if (errorResult && errorResult.value !== undefined && errorResult.value !== null) {
                throw new Error(`Failed to create Volcano API instance: ${errorResult.value}`);
            }
            
            if (apiResult && apiResult.value !== undefined && apiResult.value !== null) {
                console.log(`Volcano API实例创建成功，模型: ${config.modelId}`);
                // 创建VolcanoApi对象并返回
                const volcanoApi = new VolcanoApi(this.luaRpc, apiId);
                return volcanoApi;
            } else {
                throw new Error('Failed to create Volcano API instance: Unknown error');
            }
        } catch (error) {
            console.error(`创建Volcano API实例失败:`, error);
            throw error;
        }
    }
}

/**
 * 火山引擎API类
 * 表示一个火山引擎API连接实例
 */
class VolcanoApi {
    /**
     * 构造函数
     * @param {LuaRpc} luaRpc - Lua RPC实例
     * @param {string} apiId - Lua中火山引擎API对象的标识符
     */
    constructor(luaRpc, apiId) {
        this.luaRpc = luaRpc;
        this.apiId = apiId;
        this.isClosed = false;
        this.registeredFunctions = new Map(); // 存储注册的函数
        this.registeredTools = []; // 存储工具定义用于API请求
    }

    /**
     * 注册工具函数
     * @param {Function} callback - Lua函数回调
     * @param {string} name - 函数名称
     * @param {string} description - 函数用途描述
     * @param {Object} parameters - 参数表定义
     * @returns {void}
     */
    registerFunction(callback, name, description, parameters) {
        console.log(`VolcanoApi.registerFunction() 被调用，函数名: ${name}`);
        
        // 存储函数回调
        this.registeredFunctions.set(name, callback);
        
        // 创建工具定义用于API请求
        const tool = {
            type: "function",
            function: {
                name: name,
                description: description,
                parameters: parameters
            }
        };
        
        // 检查是否已存在相同名称的工具，如果有则替换
        const existingIndex = this.registeredTools.findIndex(t => 
            t.function && t.function.name === name
        );
        
        if (existingIndex >= 0) {
            this.registeredTools[existingIndex] = tool;
        } else {
            this.registeredTools.push(tool);
        }
    }

    /**
     * 调用注册的函数
     * @param {string} functionName - 函数名称
     * @param {Object} args - 函数参数
     * @returns {Promise<Object>} 函数执行结果
     */
    async invokeRegisteredFunction(functionName, args) {
        console.log(`VolcanoApi.invokeRegisteredFunction() 被调用，函数名: ${functionName}`);
        try {
            const callback = this.registeredFunctions.get(functionName);
            if (typeof callback === 'function') {
                // 调用注册的函数并返回结果
                const result = await callback(args);
                return result;
            } else {
                console.error(`未找到注册的函数: ${functionName}`);
                return { error: `Function not found: ${functionName}` };
            }
        } catch (error) {
            console.error(`调用函数失败: ${functionName}`, error);
            return { error: error.message };
        }
    }

    /**
     * 发送聊天消息
     * @param {string|Array|Object} input - 输入消息、消息数组或请求对象
     * @returns {Promise<[string|null, string|null]>} [响应内容, 错误信息]
     */
    async chat(input) {
        console.log('VolcanoApi.chat() 被调用');
        try {
            if (this.isClosed) {
                return [null, 'API instance is closed'];
            }
            
            // 构建请求对象，包含注册的工具
            let requestBody;
            if (typeof input === 'string') {
                requestBody = {
                    model: "doubao-seed-1-6-flash-250828",
                    messages: [
                        {
                            role: "user",
                            content: input
                        }
                    ]
                };
            } else if (Array.isArray(input)) {
                requestBody = {
                    model: "doubao-seed-1-6-flash-250828",
                    messages: input
                };
            } else if (typeof input === 'object') {
                requestBody = input;
            } else {
                return [null, 'Invalid input format. Must be string, array or object'];
            }
            
            // 如果有注册的工具，添加到请求体
            if (this.registeredTools.length > 0) {
                requestBody.tools = this.registeredTools;
            }
            
            // 转换请求体为Lua可接受的格式
            const requestString = JSON.stringify(requestBody)
                .replace(/\\"/g, '\\\\"')
                .replace(/"/g, '\\"');
            
            // 执行API对象的chat方法
            const luaCode = `
                response, resp_err = ${this.apiId}:chat("${requestString}")
            `;
            console.log(`执行Lua代码:`, luaCode);
            await this.luaRpc.runCode(luaCode);
            
            // 获取响应和错误信息
            const responseResult = await this.luaRpc.getGlobal('response');
            const respErrResult = await this.luaRpc.getGlobal('resp_err');
            
            const response = responseResult && responseResult.value !== undefined ? responseResult.value : null;
            const respErr = respErrResult && respErrResult.value !== undefined ? respErrResult.value : null;
            
            if (respErr) {
                return [null, respErr];
            }
            
            // 尝试解析响应为JSON对象以检查是否需要工具调用
            let parsedResponse;
            if (typeof response === 'string') {
                try {
                    parsedResponse = JSON.parse(response);
                } catch (e) {
                    // 如果解析失败，直接返回原始响应
                    return [response, null];
                }
            } else {
                parsedResponse = response;
            }
            
            // 检查是否需要调用工具
            if (parsedResponse.choices && parsedResponse.choices[0] && 
                parsedResponse.choices[0].finish_reason === 'tool_calls' &&
                parsedResponse.choices[0].message && parsedResponse.choices[0].message.tool_calls) {
                
                // 处理工具调用
                const toolCalls = parsedResponse.choices[0].message.tool_calls;
                const functionResults = {};
                
                for (const toolCall of toolCalls) {
                    if (toolCall.type === 'function' && toolCall.function) {
                        const { name, arguments: argsStr } = toolCall.function;
                        let args;
                        try {
                            args = JSON.parse(argsStr);
                        } catch (e) {
                            console.error(`解析工具参数失败: ${argsStr}`, e);
                            args = {};
                        }
                        
                        // 调用注册的函数
                        const result = await this.invokeRegisteredFunction(name, args);
                        functionResults[name] = result;
                    }
                }
                
                // 将函数结果添加到响应中并返回
                parsedResponse.function_results = functionResults;
                return [JSON.stringify(parsedResponse), null];
            }
            
            return [response, null];
        } catch (error) {
            console.error('调用Volcano API chat方法失败', error);
            return [null, error.message || 'Chat request failed'];
        }
    }

    /**
     * 获取对话历史
     * @returns {Promise<Array>} 对话历史数组
     */
    async getConversationHistory() {
        console.log('VolcanoApi.getConversationHistory() 被调用');
        try {
            if (this.isClosed) {
                return [];
            }
            
            // 执行API对象的getConversationHistory方法
            const luaCode = `
                history_json = cjson.encode(${this.apiId}:getConversationHistory())
            `;
            console.log(`执行Lua代码:`, luaCode);
            await this.luaRpc.runCode(luaCode);
            
            // 获取对话历史
            const historyResult = await this.luaRpc.getGlobal('history_json');
            
            if (historyResult && historyResult.value !== undefined) {
                try {
                    return JSON.parse(historyResult.value);
                } catch (e) {
                    console.error('Failed to parse conversation history:', e);
                    return [];
                }
            } else {
                return [];
            }
        } catch (error) {
            console.error('获取对话历史失败', error);
            return [];
        }
    }

    /**
     * 清空对话历史
     * @returns {Promise<void>}
     */
    async clearConversationHistory() {
        console.log('VolcanoApi.clearConversationHistory() 被调用');
        try {
            if (this.isClosed) {
                return;
            }
            
            // 执行API对象的clearConversationHistory方法
            const luaCode = `${this.apiId}:clearConversationHistory()`;
            console.log(`执行Lua代码:`, luaCode);
            await this.luaRpc.runCode(luaCode);
        } catch (error) {
            console.error('清空对话历史失败', error);
        }
    }

    /**
     * 关闭API实例
     * @returns {Promise<boolean>} - 返回操作是否成功
     */
    async close() {
        console.log('VolcanoApi.close() 被调用');
        try {
            if (!this.isClosed) {
                // 执行API对象的close方法
                const luaCode = `${this.apiId}:close()`;
                console.log(`执行Lua代码:`, luaCode);
                await this.luaRpc.runCode(luaCode);
                
                // 清理Lua中的API对象引用
                await this.luaRpc.runCode(`${this.apiId} = nil`);
                
                this.isClosed = true;
                console.log('Volcano API实例已成功关闭');
            } else {
                console.log('Volcano API实例已经关闭');
            }
            return true;
        } catch (error) {
            console.error('关闭Volcano API实例失败', error);
            return false;
        }
    }
}

/**
 * 导出VolcanoApiRpc类到全局对象
 */
// 浏览器环境中，添加到全局对象
if (typeof self !== 'undefined') {
    self.VolcanoApiRpc = VolcanoApiRpc;
}

// 兼容旧版浏览器的window对象
if (typeof window !== 'undefined') {
    window.VolcanoApiRpc = VolcanoApiRpc;
}

// 导出模块供Node.js环境使用
if (typeof module !== 'undefined' && module.exports) {
    module.exports = {
        VolcanoApiRpc: VolcanoApiRpc
    };
}